﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.TeamFoundation.Build.Client;
using System.Activities;
using Microsoft.TeamFoundation.Build.Workflow;
using System.Threading;
using Microsoft.TeamFoundation.Build.Workflow.Tracking;
using Microsoft.TeamFoundation.Build.Workflow.Activities;

namespace TFSBuildActivitiesLibrary
{
    class Utilities
    {
        internal static IQueuedBuild BeginExecute(CodeActivityContext context, IBuildDetail buildDetail, 
                                            string buildDefinitionName, IDictionary<string, object> dictInputArguments)
        {
            IBuildDefinitionSpec buildDefSpec = buildDetail.BuildServer.CreateBuildDefinitionSpec(buildDetail.TeamProject, buildDefinitionName);
            buildDefSpec.Options = QueryOptions.Definitions;
            IBuildDefinitionQueryResult results = buildDetail.BuildServer.QueryBuildDefinitions(buildDefSpec);

            if (results.Failures.Length != 0)
            {
                foreach (IFailure mess in results.Failures)
                {
                    TrackMessage(context, "Falied to query build definition \"" + buildDefinitionName + "\". Failure message: " + mess.ToString());
                }
                return null;
            }

            IBuildDefinition buildDefinition = results.Definitions[0];
            string itmKey = "";
            try
            {
                IBuildRequest buildReq = buildDetail.BuildServer.CreateBuildRequest(buildDefinition.Uri, buildDetail.BuildControllerUri);
                buildReq.DropLocation = buildDetail.DropLocationRoot;

                IDictionary<String, Object> paramValues = WorkflowHelpers.DeserializeProcessParameters(buildReq.ProcessParameters);
                IDictionary<String, Object> paramValues2 = WorkflowHelpers.DeserializeProcessParameters(buildDefinition.ProcessParameters);

                foreach (var itm in dictInputArguments)
                {
                    itmKey = itm.Key;
                    paramValues[itm.Key] = itm.Value;
                }
                itmKey = "";

                buildReq.ProcessParameters = WorkflowHelpers.SerializeProcessParameters(paramValues);

                IQueuedBuild queuedBuild = buildDetail.BuildServer.QueueBuild(buildReq, QueueOptions.None);
                TrackMessage(context, "Queued build: \"" + buildDefinitionName + "\", build status is: " + queuedBuild.Status.ToString());

                return queuedBuild;
            }
            catch (Exception ex)
            {
                var trace = new System.Diagnostics.StackTrace(ex, true);
                var strbld = new StringBuilder();

                strbld.AppendLine("Queue New Build error: " + ex);
                if (ex is KeyNotFoundException) strbld.AppendLine("Key not found: " + itmKey);

                strbld.AppendLine(trace.GetFrame(0).GetMethod().ReflectedType.FullName);
                strbld.AppendLine("Line: " + trace.GetFrame(0).GetFileLineNumber());
                strbld.AppendLine("Column: " + trace.GetFrame(0).GetFileColumnNumber());

                TrackMessage(context, strbld.ToString());
                return null;
            }
        }

        internal static void EndExecute(CodeActivityContext context, IQueuedBuild queuedBuild, string strBuildQuality)
        {
            try
            {
                while (queuedBuild.Status != QueueStatus.Completed && queuedBuild.Status != QueueStatus.Canceled)
                {
                    Thread.Sleep(10000);
                    queuedBuild.Refresh(QueryOptions.Definitions);
                }

                if (queuedBuild.Build != null && strBuildQuality != "Undefined")
                {
                    queuedBuild.Build.Quality = strBuildQuality;
                }

                return;
            }
            catch (Exception ex)
            {
                var trace = new System.Diagnostics.StackTrace(ex, true);
                var strbld = new StringBuilder();

                strbld.AppendLine("Queue New Build error: " + ex);
                strbld.AppendLine(trace.GetFrame(0).GetMethod().ReflectedType.FullName);
                strbld.AppendLine("Line: " + trace.GetFrame(0).GetFileLineNumber());
                strbld.AppendLine("Column: " + trace.GetFrame(0).GetFileColumnNumber());

                TrackMessage(context, strbld.ToString());
                return;
            }
        }

        internal static void TrackMessage(CodeActivityContext context, string message)
        {
            //context.TrackBuildMessage(message, BuildMessageImportance.High);
            context.Track(
                new BuildInformationRecord<BuildMessage>()
                {
                    Value = new BuildMessage() { Importance = BuildMessageImportance.High, Message = message }
                });
        }
    }
}
